<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <script>
    Function.prototype.call2 = function (context) {
      context = context || window;
      context.fn = this;
      let args = [];
      //eval eval() 的参数是一个字符串。如果字符串表示的是表达式，
      //eval() 会对表达式进行求值。如果参数表示一个或多个 JavaScript 语句，那么eval() 就会执行这些语句。
      //如果 eval() 的参数不是字符串， eval() 会将参数原封不动地返回。
      //使用 eval 给数组中的 arguments[1] arguments[2] 做处理
      //这里必须得传入 arguments 而不是真实值的原因是，假如传入真实值并且值为字符串，eval会对字符串做处理，就变成 context.fn(kevin,18)
      //所以报错 kevin 没有定义
      //而传 arguments 则会从父级作用域拿到真实值。
      // for (let i = 1; i < arguments.length; i++) {
      //   args.push(`arguments[${i}]`);
      // }
      // let res = eval(`context.fn(${args})`);
      // es6 通过对数组展开，来给 context.fn 传值
      for (let i = 1; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
      let res = context.fn(...args)
      delete context.fn;
      return res;
    }

    var value = 2;

    function bar(name, age) {
      console.log(name)
      console.log(age)
      console.log(this.value);
    }

    var foo = {
      value: 1
    };

    bar.call2(foo, 'kevin', 18);
  </script>
</body>

</html>